#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>
#include <locale.h>
//uart.c
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>

int fd; // ÎÄ¼þÃèÊö·û£¬ÓÃÓÚ´®¿ÚÍ¨ÐÅ
unsigned char receive_buff[100]; // ½ÓÊÕ»º³åÇø£¬´óÐ¡Îª50×Ö½Ú 
unsigned int receive_num = 0; // Êµ¼Ê½ÓÊÕµÄÊý¾Ý³¤¶È
unsigned char send_buff[100] = "test serial port"; // ·¢ËÍ»º³åÇø£¬³õÊ¼»¯Îª"test serial port" 
unsigned int send_num = 0; // Êµ¼Ê·¢ËÍµÄÊý¾Ý³¤¶È

// º¯ÊýÉùÃ÷£ºÍ¨¹ýÎÄ¼þÃèÊö·ûfd·¢ËÍÊý¾ÝÖ¡
int func_send_frame(int fd, const unsigned char* p_send_buff, const int count)
{
	int Result = 0; // ·¢ËÍ½á¹û±äÁ¿
	// Ê¹ÓÃwriteÏµÍ³µ÷ÓÃ·¢ËÍÊý¾Ý
	Result = write(fd, p_send_buff, count);
	if (Result == -1) { // Èç¹û·¢ËÍÊ§°Ü
		perror("write"); // ´òÓ¡´íÎóÐÅÏ¢
		return 0; // ·µ»Ø0±íÊ¾·¢ËÍÊ§°Ü
	}
	return Result; // ·µ»ØÊµ¼Ê·¢ËÍµÄÊý¾Ý³¤¶È
}

// º¯ÊýÉùÃ÷£ºÍ¨¹ýÎÄ¼þÃèÊö·ûfd½ÓÊÕÊý¾ÝÖ¡
int func_receive_frame(int fd, unsigned char* p_receive_buff, const int count)
{
	int nread = 0; // Êµ¼Ê¶ÁÈ¡µÄÊý¾Ý³¤¶È
	fd_set rd; // ÎÄ¼þÃèÊö·û¼¯ºÏ£¬ÓÃÓÚselectÏµÍ³µ÷ÓÃ
	int retval = 0; // selectÏµÍ³µ÷ÓÃµÄ½á¹û
	struct timeval timeout = { 0, 500 }; // ÉèÖÃ³¬Ê±Ê±¼äÎª500Î¢Ãë

	FD_ZERO(&rd); // Çå¿ÕÎÄ¼þÃèÊö·û¼¯ºÏ
	FD_SET(fd, &rd); // ½«ÎÄ¼þÃèÊö·ûfd¼ÓÈë¼¯ºÏ
	memset(p_receive_buff, 0x0, count); // ³õÊ¼»¯½ÓÊÕ»º³åÇøÎª0

	// Ê¹ÓÃselectÏµÍ³µ÷ÓÃµÈ´ýÎÄ¼þÃèÊö·û¿É¶Á
	retval = select(fd + 1, &rd, NULL, NULL, &timeout);
	switch (retval) {
	case 0: // ³¬Ê±£¬Ã»ÓÐÊý¾Ý¿É¶Á
		nread = 0;
		break;
	case -1: // selectÏµÍ³µ÷ÓÃ³ö´í
		printf("select %s\n", strerror(errno)); // ´òÓ¡´íÎóÐÅÏ¢
		nread = -1;
		break;
	default: // ³É¹¦¶ÁÈ¡Êý¾Ý
		nread = read(fd, p_receive_buff, count); // Ê¹ÓÃreadÏµÍ³µ÷ÓÃ¶ÁÈ¡Êý¾Ý
		break;
	}
	return nread; // ·µ»ØÊµ¼Ê¶ÁÈ¡µÄÊý¾Ý³¤¶È
}

int uart_open()
{
	int result = 0;
	struct termios newtio, oldtio;
	//´ò¿ª´®¿Ú uart9 ÉèÖÃ¿É¶ÁÐ´£¬²»±»ÊäÈëÓ°Ïì£¬²»µÈ´ýÍâÉèÏìÓ¦
	fd = open("/dev/ttyS9", O_RDWR | O_NOCTTY | O_NDELAY);
	if (fd < 0) {
		perror("/dev/ttyS9");
		printf("Can't Open Serial Port %s \n", "/dev/ttyS9");
		exit(0);
	}
	else {
		//ÉèÖÃ´®¿Ú²ÎÊý
		if (tcgetattr(fd, &oldtio) != 0) {
			perror("tcgetattr");
			return -1;
		}
		bzero(&newtio, sizeof(newtio)); //Çå¿Õ´®¿ÚÉèÖÃ
		newtio.c_cflag |= CLOCAL | CREAD; //´ò¿ª½ÓÊÕ±êÖ¾ºÍºöÂÔ¿ØÖÆÏß
		newtio.c_cflag &= ~CSIZE; //Çå³ýÊý¾ÝÎ»ÉèÖÃ
		newtio.c_cflag |= CS8; //ÉèÖÃÊý¾ÝÎ»Îª 8 Î»
		newtio.c_cflag &= ~PARENB; //ÎÞÐ£ÑéÎ»
		cfsetispeed(&newtio, B115200); //ÉèÖÃÊäÈë²¨ÌØÂÊÎª 115200
		cfsetospeed(&newtio, B115200); //ÉèÖÃÊä³ö²¨ÌØÂÊÎª 115200
		newtio.c_cflag &= ~CSTOPB; //ÉèÖÃÍ£Ö¹Î» 1
		newtio.c_cc[VTIME] = 0; //²»Ê¹ÓÃ³¬Ê±¿ØÖÆ
		newtio.c_cc[VMIN] = 0; //²»µÈ´ý×Ö·û
		tcflush(fd, TCIFLUSH); //´®¿ÚÊý¾ÝË¢ÐÂ
		if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
			perror("com set error");
			close(fd);
			return -1;
		}
		else {
			printf("set done!\n");
		}
	}
	return fd;
}
// Ð­Òé¶¨Òå
#define PACKET_HEADER 0xFD
#define CMD_TYPE 0x01
#define SUB_TYPE 0x01  // ¸ù¾ÝÉè±¸ÎÄµµÈ·ÈÏ×ÓÀàÐÍ


// UTF8×ªGB2312º¯Êý
int utf8_to_gb2312(const char* inbuf, size_t inlen, char** outbuf, size_t* outlen) {
    iconv_t cd = iconv_open("GB2312", "UTF-8");
    if (cd == (iconv_t)-1) {
        perror("iconv_open");
        return -1;
    }

    size_t outbytes_left = inlen * 2; // ·ÖÅä×ã¹»»º³åÇø
    *outbuf = malloc(outbytes_left);
    char* outptr = *outbuf;

    if (iconv(cd, (char**)&inbuf, &inlen, &outptr, &outbytes_left) == (size_t)-1) {
        perror("iconv");
        iconv_close(cd);
        return -1;
    }

    *outlen = outptr - *outbuf;
    iconv_close(cd);
    return 0;
}

unsigned char* utf8Tran(const char* inputString, size_t* outLength) {
	// ±àÂë×ª»»
	char* gb2312_text = NULL;
	size_t gb_len = 0;
	if (utf8_to_gb2312(inputString, strlen(inputString), &gb2312_text, &gb_len) != 0) {
		return NULL;
	}

	// Ð­Òé³¤¶È¼ÆËã
	size_t data_length = gb_len + 2;  // ÃüÁî×Ö¶ÎÕ¼2×Ö½Ú
	size_t total_length = 3 + data_length; // °üÍ·3×Ö½Ú + Êý¾Ý³¤¶È

	// ¹¹½¨°üÍ·ºÍÈÎÎñ±êÇ©
	unsigned char header[] = {
		PACKET_HEADER,
		(unsigned char)((data_length >> 8) & 0xFF),
		(unsigned char)(data_length & 0xFF)
	};
	unsigned char taskLabel[] = { CMD_TYPE, SUB_TYPE };

	// ·ÖÅäÄÚ´æ²¢×é×°Êý¾Ý°ü
	unsigned char* result = (unsigned char*)malloc(total_length);
	if (!result) {
		free(gb2312_text);
		return NULL;
	}

	memcpy(result, header, 3);
	memcpy(result + 3, taskLabel, 2);
	memcpy(result + 5, gb2312_text, gb_len);

	// ÊÍ·ÅÖÐ¼ä±àÂë×ª»»½á¹û
	free(gb2312_text);

	// ÉèÖÃÊä³ö³¤¶È£¨Èç¹û²ÎÊýÓÐÐ§£©
	if (outLength) {
		*outLength = total_length;
	}

	// µ÷ÊÔÊä³ö£¨¿ÉÑ¡±£Áô£©
	printf("完整协议包(%zu字节):\n", total_length);
	for (size_t i = 0; i < total_length; i++) {
		printf("%02X ", result[i]);
	}
	printf("\n");

	return result;
}

int send_speak(const char* input) {
	int result = 0;

	result = uart_open();
	if (result < 0) {
		printf("Failed to open and configure UART.\n");
		return -1;  // 修改exit为return保持函数封装性
	}

	setlocale(LC_ALL, "en_US.UTF-8");
	printf("发送文本: %s\n", input);

	size_t pktLength;
	unsigned char* packet = utf8Tran(input, &pktLength);
	if (!packet) {
		close(fd);  // 增加关闭文件描述符
		return -1;
	}

	send_num = func_send_frame(fd, packet, pktLength);
	if (send_num > 0) {
		printf("[发送字节数=%d] ", send_num);
		for (int i = 0; i < send_num; i++) {
			printf("%02X ", packet[i]);
		}
		printf("\n");
	}
	else {
		printf("发送失败\n");
	}

	free(packet);
	sleep(1);
	close(fd);
	return (send_num > 0) ? 0 : -1;  // 返回明确的状态码
}


int menu_send(const char* category, const char* check_result) {
    // 状态映射：将"new"转换为"新鲜"
    const char* status_text = "未知状态"; // 默认值
    
    if (check_result) {
        // 不区分大小写比较
        if (strcasecmp(check_result, "new") == 0) {
            status_text = "新鲜";
        } else if (strcasecmp(check_result, "moldy") == 0) {
            status_text = "不新鲜，已变质";
        } else {
            // 其他情况使用原始值
            status_text = check_result;
        }
    }

    // 构建固定格式的字符串
    char message_buffer[128];
    snprintf(message_buffer, sizeof(message_buffer),
            "为您识别到的菜品为“%s”，当前菜品状况为“%s”",
            category ? category : "未知菜品",
            status_text);

    // 发送构造好的语句
    int ret = send_speak(message_buffer);

    if (ret != 0) {
        printf("发送失败。错误代码: %d\n", ret);
        return -1;
    }

    return 0;
}


int food_send(const char* recommended_dish, const char* user_preferences) {

    const char* status_text = "未知状态"; // 默认值
    // 构建固定格式的字符串
    char message_buffer[128];
    snprintf(message_buffer, sizeof(message_buffer),
            "为您推荐到的菜品为“%s”，当前用户习惯为“%s”",
            recommended_dish ? recommended_dish : "未知菜品",
            status_text);

    // 发送构造好的语句
    int ret = send_speak(message_buffer);

    if (ret != 0) {
        printf("发送失败。错误代码: %d\n", ret);
        return -1;
    }

    return 0;
}

int his_send(const char* his_dish) {
    char message_buffer[128];
    
    
    snprintf(message_buffer, sizeof(message_buffer),
            "为您查询到上次的菜品为“%s”",  
            his_dish);  // 使用%%显示百分号

    int ret = send_speak(message_buffer);
    if (ret != 0) {
        printf("发送失败。错误代码: %d\n", ret);
        return -1;
    }
    return 0;
}


int aht20_send(float temp, float hum) {
    char message_buffer[128];
    
    
    snprintf(message_buffer, sizeof(message_buffer),
            "当前温度为“%.1f℃”，当前湿度为“%.1f%%”",  // 改用%f格式，添加单位
            temp,  // float自动提升为double
            hum);  // 使用%%显示百分号

    int ret = send_speak(message_buffer);
    if (ret != 0) {
        printf("发送失败。错误代码: %d\n", ret);
        return -1;
    }
    return 0;
}